<template>
  <div :style="styleObj">
    <div class="grade-container">
      <div v-for="item in list" :key="item.name" class="item">
        <span class="dot" :style="{ background: item.color }"></span>
        <span class="name">{{ item.name }}</span>
      </div>
    </div>
    <div id="tree-graph-container" style="height: calc(100% - 40px)"></div>
  </div>
</template>

<script>
import G6 from '@antv/g6';
import { getRelationList } from '@/api/customerMaintain.js';
const colorList = {
  1: '#5e6ffd',
  2: '#96e72a',
  3: '#2ce6a5',
  4: '#ff743e',
};

const getLastId = (data) => {
  const top = data.filter((item) => item.rankCode === '1');
  const topObj = top.reduce((pre, cur) => {
    pre[cur.id] = cur;
    return pre;
  }, {});
  const depthObj = top.reduce((pre, cur) => {
    let currentId = cur.id;
    let pid = topObj[currentId].pid;
    let depth = 0;
    while (pid !== 'null') {
      depth += 1;
      currentId = pid;
      pid = topObj[currentId].pid;
    }
    pre[cur.id] = depth;
    return pre;
  }, {});
  return Object.keys(depthObj).reduce((pre, cur) => {
    const dep = depthObj[pre] || 0;
    if (depthObj[cur] > dep) {
      pre = cur;
    }
    return pre;
  }, '');
};

const createData = (data = []) => {
  const nodes = [
    {
      id: 'empty',
    },
  ];
  const formatNode = data.map((item) => {
    const comboId = item.rankCode === '1' ? '高管' : item.professionName;
    return {
      ...item,
      id: String(item.id),
      pid: String(item.pid),
      comboId,
    };
  });
  nodes.push(...formatNode.map((item) => ({ ...item })));

  const lastId = getLastId(formatNode);
  const edges = formatNode.reduce(
    (pre, cur) => {
      if (cur.rankCode === '1' && cur.pid === 'null') return pre;
      pre.push({
        target: cur.id,
        source: cur.pid === 'null' ? 'empty' : cur.pid,
      });
      return pre;
    },
    [
      {
        target: 'empty',
        source: lastId,
      },
    ]
  );
  const combosObj = formatNode.reduce(
    (pre, cur) => {
      if (cur.professionName) {
        pre[cur.professionName] = cur.professionName;
      }
      return pre;
    },
    { 高管: '高管' }
  );
  const combos = Object.keys(combosObj).map((item) => {
    return {
      id: item,
      label: item,
    };
  });
  return {
    nodes,
    edges,
    combos,
  };
};
// const data = createData(Mockdata);
// console.log('data: ', data);

export default {
  props: {
    code: {
      type: String,
      // default: 'Cust00000185',
      default: '',
    },
  },
  data() {
    this.list = [
      {
        name: '高管',
        color: colorList[1],
      },
      {
        name: '一级',
        color: colorList[2],
      },
      {
        name: '二级',
        color: colorList[3],
      },
      {
        name: '三级',
        color: colorList[4],
      },
    ];
    return {};
  },
  computed: {
    styleObj() {
      const height = 'calc(100vh - 200px)';
      return {
        height,
      };
    },
  },
  async mounted() {
    const textXML = (cfg) => {
      let name = cfg.node.name || '';
      name = name.length > 4 ? name.slice(0, 4) + '...' : name;
      return `
        <group>
          <circle style={{r: 40, fill: ${
            cfg.style.fill
          }}} keyshape="true" name="container">
              <text style={{fill: #fff, textAlign: center, marginTop: -8, fontSize: 16}}>${name}</text>
              <text style={{marginLeft: 50, marginTop: -20, fontSize: 14, fill: ${
                cfg.node.id === 'empty' ? '#fff' : '#000'
              }}}>${cfg.node.position || ''}
              </text>
              <text style={{marginLeft: 50, marginTop: -30, fontSize: 14}}>${
                cfg.node.department || ''
              }</text>
              <text style={{marginLeft: 50, marginTop: -24, fontSize: 14, fill: ${
                cfg.node.id === 'empty' ? '#fff' : '#000'
              }}}>拜访：${cfg.node.visitCount || 0} 次</text>
          </circle>
        </group>
        `;
    };
    G6.registerNode('my-circle', {
      jsx: textXML,
      getAnchorPoints() {
        return [
          [0.5, 0],
          [0.5, 1],
        ];
      },
    });

    if (!this.code) return;
    const result = await getRelationList({
      // customerCode: 'Cust00000185',
      customerCode: this.code,
    });
    const list = result?.data?.data || [];
    const data = createData(list);

    const container = document.getElementById('tree-graph-container');
    const width = container.scrollWidth;
    const height = container.scrollHeight || 500;

    const tooltip = new G6.Tooltip({
      offsetX: 10,
      offsetY: 20,
      fixToNode: true,
      getContent(e) {
        const node = e.item.getModel() || {};
        if (node.id === 'empty') return '';
        const outDiv = document.createElement('div');
        outDiv.style.width = '180px';
        outDiv.innerHTML = `
        <h5>${node.name || ''}</h5>
        <h5>${node.position || ''} </h5>
        <h5>${node.department || ''}</h5>
        <h5>拜访：<span style="color: blue">${
          node.visitCount || 0
        } </span>次</h5>
        `;
        return outDiv;
      },
      itemTypes: ['node'],
    });

    const graph = new G6.Graph({
      container,
      width,
      height,
      fitView: true,
      fitViewPadding: 30,
      plugins: [tooltip],
      animate: true,
      groupByTypes: false,
      sortByCombo: true,
      modes: {
        default: [
          'drag-combo',
          'drag-canvas',
          'zoom-canvas',
          {
            type: 'collapse-expand-combo',
            relayout: false,
          },
        ],
      },
      layout: {
        type: 'dagre',
        sortByCombo: false,
        ranksep: 20,
        nodesep: 40,
      },
      defaultNode: {
        type: 'my-circle',
      },
      // defaultNode: {
      //   size: 40,
      //   type: 'circle',
      //   anchorPoints: [
      //     [0.5, 0],
      //     [0.5, 1],
      //   ],
      // },

      defaultEdge: {
        type: 'line',
      },
      defaultCombo: {},
    });

    graph.node((node) => {
      const isEmpty = node.id === 'empty';
      if (isEmpty) {
        return {
          label: ' ', // 必须有个空格才不显示
          node,
          style: {
            lineWidth: 0,
            fill: '#fff',
            stroke: '#fff',
            opacity: 1,
          },
        };
      }
      return {
        // type: 'my-circle',
        size: 100,
        node,
        label: `
        ${node.name || ''}
        ${node.position || ''} ${node.visitCount || 0} 次
        ${node.department || ''}
        `,
        style: {
          fill: colorList[node.rankCode] || '#5e6ffd',
          stroke: colorList[node.rankCode] || '#5e6ffd',
        },
        labelCfg: {
          position: 'right',
          offset: -100,
          style: {
            textAlign: 'left',
            fill: '#fff',
          },
        },
      };
    });

    graph.edge((edge) => {
      const source = edge.source;
      const target = edge.target;
      const noLine = source?.includes('empty') || target?.includes('empty');
      return {
        style: {
          lineWidth: noLine ? 0 : 1,
        },
      };
    });

    graph.combo((combo) => {
      return {
        type: 'rect',
        padding: [35, 100, 15, 20],
        style: {
          fillOpacity: 0.1,
          // fill: '#c4e382',
        },

        labelCfg: {
          style: {
            fontSize: 24,
            fontWeight: 600,
          },
        },
      };
    });

    graph.data(data);
    graph.render();
    graph.fitView();

    if (typeof window !== 'undefined')
      window.onresize = () => {
        if (!graph || graph.get('destroyed')) return;
        if (!container || !container.scrollWidth || !container.scrollHeight)
          return;
        graph.changeSize(container.scrollWidth, container.scrollHeight);
      };
  },

  methods: {},
};
</script>

<style lang="less" scoped>
.grade-container {
  display: flex;
  justify-content: flex-end;
  .item {
    margin-left: 10px;
  }
  .dot {
    margin-right: 4px;
    height: 10px;
    width: 10px;
    border-radius: 50%;
    display: inline-block;
  }
}
</style>>
